#include <iostream>
#include <opencv/cv.h>
#include "quadil.hpp"
#include <opencv/highgui.h>

int main(int argc,char** argv){
	int arg=1;
	while(arg<argc){
		try{
			quadil::Image<quadil::t_byte> i=quadil::cv::loadByteImage(argv[arg]);
			i.subtractFrom(255);
			quadil::Image<quadil::t_byte> der1(i.width,i.height);
			quadil::Image<quadil::t_byte> der2(i.width,i.height);
			quadil::Image<quadil::t_byte> der(i.width,i.height);
			i.getAbsDerivativeHorizontal(der1);
			i.getAbsDerivativeHorizontal(der2);
			der.accumulateWeightedSum<2>(&der1,1.0,&der2,1.0);
			der.normaliseLinearly(0,255);
			der.subtractFrom(255);
			quadil::AccumulatedImage<long long int,quadil::t_byte> acc(i);
			i.subtractFrom(255);

			std::cout<<"main 3\n";
			quadil::Image<quadil::t_label> res(i.width,i.height);
			res.setAll(0);
			quadil::Spliter<quadil::AccumulatedImage<long long int,quadil::t_byte> > spliter(acc);
			std::cout<<"main 4\n";
			spliter.splitHoriz(
					quadil::Spliter<quadil::AccumulatedImage<long long int,quadil::t_byte> >::Rect
					(0,0,i.width-1,i.height-1),50);
			spliter.print();
			spliter.draw(res);
			cvNamedWindow("Top",0);
			cvNamedWindow("Regions",0);
			cvNamedWindow("Original",0);
			cvNamedWindow("Deriv",0);
			cvResizeWindow("Top",500,400);
			cvResizeWindow("Regions",500,400);
			cvResizeWindow("Deriv",500,400);
			cvResizeWindow("Original",500,400);
			cvMoveWindow("Top",10,10);
			cvMoveWindow("Deriv",530,10);
			cvMoveWindow("Regions",10,450);
			cvMoveWindow("Original",530,450);


			//quadil::cv::drawByteImage("Top",top);
			std::cout<<"main 5\n";
			quadil::Image<quadil::t_byte> mask=i.deepCopy();
			mask.subtractFrom(255);
			mask.binarize(100,0,255);
			//mask.subtractFrom(255);
			quadil::cv::showLabelImage(res,"Regions");

			res.applyMaskGeneric<quadil::t_byte>(mask);
			quadil::cv::showLabelImage(res,"Top");

			quadil::cv::drawByteImage("Deriv",der);
			quadil::cv::drawByteImage("Original",i);
			cvWaitKey(0);
			cvDestroyAllWindows();
		}catch(const char* c){
			std::cerr<<"Exception:\n"<<c<<"\n";
		}
		arg++;
	}
}
/*

int main(int argc,char** argv){
	quadil::util::Timer t;
	quadil::Image<quadil::t_byte> i=quadil::cv::loadByteImage(argv[1]);
	quadil::Image<quadil::t_byte> nw(i.width,i.height);
	quadil::Image<quadil::t_byte> nc(i.width,i.height);
	quadil::Image<quadil::t_byte> ne(i.width,i.height);
	quadil::Image<quadil::t_byte> ce(i.width,i.height);
	quadil::Image<quadil::t_byte> se(i.width,i.height);
	quadil::Image<quadil::t_byte> sc(i.width,i.height);
	quadil::Image<quadil::t_byte> sw(i.width,i.height);
	quadil::Image<quadil::t_byte> cw(i.width,i.height);
	quadil::Image<quadil::t_byte> inw(i.width,i.height);
	quadil::Image<quadil::t_byte> inc(i.width,i.height);
	quadil::Image<quadil::t_byte> ine(i.width,i.height);
	quadil::Image<quadil::t_byte> ice(i.width,i.height);
	quadil::Image<quadil::t_byte> ise(i.width,i.height);
	quadil::Image<quadil::t_byte> isc(i.width,i.height);
	quadil::Image<quadil::t_byte> isw(i.width,i.height);
	quadil::Image<quadil::t_byte> icw(i.width,i.height);

	i.getAbsDerivativeDiagonalTLBR(nw,quadil::Image<quadil::t_byte>::ABS_DERIVATION_ASCEND);
	i.getAbsDerivativeDiagonalTLBR(se,quadil::Image<quadil::t_byte>::ABS_DERIVATION_DESCEND);
	i.getAbsDerivativeDiagonalTRBL(ne,quadil::Image<quadil::t_byte>::ABS_DERIVATION_ASCEND);
	i.getAbsDerivativeDiagonalTRBL(sw,quadil::Image<quadil::t_byte>::ABS_DERIVATION_DESCEND);
	i.getAbsDerivativeHorizontal(cw,quadil::Image<quadil::t_byte>::ABS_DERIVATION_ASCEND);
	i.getAbsDerivativeHorizontal(ce,quadil::Image<quadil::t_byte>::ABS_DERIVATION_DESCEND);
	i.getAbsDerivativeVertical(nc,quadil::Image<quadil::t_byte>::ABS_DERIVATION_ASCEND);
	i.getAbsDerivativeVertical(sc,quadil::Image<quadil::t_byte>::ABS_DERIVATION_DESCEND);
	i.getAbsDerivativeDiagonalTLBR(inw,quadil::Image<quadil::t_byte>::ABS_DERIVATION_ASCEND);
	i.getAbsDerivativeDiagonalTLBR(ise,quadil::Image<quadil::t_byte>::ABS_DERIVATION_DESCEND);
	i.getAbsDerivativeDiagonalTRBL(ine,quadil::Image<quadil::t_byte>::ABS_DERIVATION_ASCEND);
	i.getAbsDerivativeDiagonalTRBL(isw,quadil::Image<quadil::t_byte>::ABS_DERIVATION_DESCEND);
	i.getAbsDerivativeHorizontal(icw,quadil::Image<quadil::t_byte>::ABS_DERIVATION_ASCEND);
	i.getAbsDerivativeHorizontal(ice,quadil::Image<quadil::t_byte>::ABS_DERIVATION_DESCEND);
	i.getAbsDerivativeVertical(inc,quadil::Image<quadil::t_byte>::ABS_DERIVATION_ASCEND);
	i.getAbsDerivativeVertical(isc,quadil::Image<quadil::t_byte>::ABS_DERIVATION_DESCEND);
	inw.subtractFrom(255);
	inc.subtractFrom(255);
	ine.subtractFrom(255);
	ice.subtractFrom(255);
	ise.subtractFrom(255);
	isc.subtractFrom(255);
	ise.subtractFrom(255);
	icw.subtractFrom(255);
	quadil::Image<quadil::t_byte> top(i.width,i.height);
	quadil::Image<quadil::t_byte> bottom(i.width,i.height);
	quadil::Image<quadil::t_byte> left(i.width,i.height);
	quadil::Image<quadil::t_byte> right(i.width,i.height);
	quadil::Image<quadil::t_byte> reconstruct(i.width,i.height);
	quadil::Image<quadil::t_byte> tl(i.width,i.height);
	quadil::Image<quadil::t_byte> tr(i.width,i.height);
	quadil::Image<quadil::t_byte> br(i.width,i.height);
	quadil::Image<quadil::t_byte> bl(i.width,i.height);


	top.accumulateWeightedProd<3>(&nc,0.5,&nw,0.10,&ne,0.1);
	top.normaliseLinearly(0,255);
	bottom.accumulateWeightedProd<3>(&sc,0.5,&sw,0.10,&se,0.1);
	bottom.normaliseLinearly(0,255);
	left.accumulateWeightedSum<3>(&ce,0.5,&se,0.10,&ne,0.1);
	left.normaliseLinearly(0,255);
	right.accumulateWeightedSum<3>(&cw,0.5,&nw,0.10,&sw,0.1);
	right.normaliseLinearly(0,255);
	tl.accumulateWeightedSum<3>(&nw,0.7,&cw,0.1,&nc,0.1);
	tl.normaliseLinearly(0,255);
	tr.accumulateWeightedSum<3>(&ne,0.7,&ce,0.1,&nc,0.1);
	tr.normaliseLinearly(0,255);
	bl.accumulateWeightedSum<3>(&sw,0.7,&cw,0.1,&sc,0.1);
	bl.normaliseLinearly(0,255);
	br.accumulateWeightedSum<3>(&se,0.7,&ce,0.1,&sc,0.1);
	br.normaliseLinearly(0,255);
	quadil::AccumulatedImage<int,quadil::t_byte> Acc(i);
	std::cout<<"Acc sum ="<<Acc.getSum(2,3,600,700)<<"\n";
	quadil::Image<quadil::t_label> res(i.width,i.height);
	res.setAll(0);
	Acc.splitVert(0,0,i.width-1,i.height-1,res,4);
	cvNamedWindow("Top",0);
	//quadil::cv::drawByteImage("Top",top);
	quadil::cv::showLabelImage(res,"Top");
	cvNamedWindow("Original",0);
	quadil::cv::drawByteImage("Original",i);
	cvWaitKey(0);
	cvDestroyAllWindows();
}
*/

/*
int main(int argc,char** argv){
	quadil::util::Timer t;
	quadil::Image<quadil::t_byte> i=quadil::cv::loadByteImage(argv[1]);
	quadil::t_byte hmin,hmax,vmin,vmax,dmin,dmax;
	quadil::Image<quadil::t_byte> horiz(i.width,i.height);
	quadil::Image<quadil::t_byte> vert(i.width,i.height);
	quadil::Image<quadil::t_byte> diag(i.width,i.height);
	i.getAbsDerivativeHorizontal(horiz);
	i.getAbsDerivativeVertical(vert);
	i.getAbsDerivativeDiagonalTLBR(diag);
	horiz.getMinMax(hmin,hmax);
	vert.getMinMax(vmin,vmax);
	diag.getMinMax(dmin,dmax);
	cvNamedWindow("Horiz",0);
	cvNamedWindow("Vert",0);
	cvNamedWindow("Diag",0);

	quadil::Image<quadil::t_byte> accum(i.width,i.height);
	t.tic();
	for(int i=0;i<100;i++)
	accum.accumulateWeightedSum<3>(&horiz,0.33,&vert,0.34,&diag,0.33);
	std::cout<<"Time elaborated "<<t.getMiliseconds()<<"ms\n";
	t.tic();
	for(int i=0;i<100;i++)
	accum.accumulateWeightedSum<2>(&horiz,0.33,&vert,0.34);
	std::cout<<"Time elaborated "<<t.getMiliseconds()<<"ms\n";
	t.tic();
	for(int i=0;i<100;i++)
	accum.accumulateWeightedSum<4>(&horiz,0.33,&vert,0.34,&diag,0.33,&diag,0.01);
	std::cout<<"Time elaborated "<<t.getMiliseconds()<<"ms\n";

	quadil::cv::drawByteImage("Horiz",horiz);
	quadil::cv::drawByteImage("Vert",vert);
	quadil::cv::drawByteImage("Diag",diag);
	quadil::cv::drawByteImage("Horiz",accum);
	cvWaitKey(0);
	cvDestroyAllWindows();
}
*/
/*
int main(int argc,char** argv){
	try{
		int k;
		std::cout<<"done\n";
		quadil::Image<quadil::t_byte> i=quadil::cv::loadByteImage(argv[1]);
		i.applyHorizontalRLSA(1,255);
		i.subtractFrom(255);
		//i.subtractFrom(255);
		cvNamedWindow("hello1",0);
//		cvNamedWindow("hello2",0);
		quadil::cv::drawByteImage("hello1",i);
		//cvWaitKey();
		quadil::util::Timer t;
		quadil::ComponentSet cs(i);
		std::cout<<"cs done in "<<t.getMiliseconds()<<"\n";
		t.tic();
		i.labelConnectedComponents8(cs);
		std::cout<<"labeling done in "<<t.getMiliseconds()<<"\n";
		class quadil::cfilter::FitsIn f(10,10);
		t.tic();
		int cc=cs.countComponents(f);
		std::cout<<"Counted components "<< cc<<"components counted in "<<t.getMiliseconds()<<"\n";
		class quadil::cfilter::FitsIn f2(100,100);
		t.tic();
		cc=cs.countComponents(f2);
		std::cout<<"Counted components "<< cc<<"components counted in "<<t.getMiliseconds()<<"\n";
		quadil::cv::ComponentSetViewer csv(cs);
		csv.guiLoop();
	}catch(const char* c){
		std::cerr<<"Exception:\n"<<c<<"\n";
	}
}
*/
